package com.duojuhe.coremodule.info.service.impl;

import com.duojuhe.common.annotation.DataScopeFilter;
import com.duojuhe.common.bean.UserTokenInfoVo;
import com.duojuhe.common.constant.DataScopeConstants;
import com.duojuhe.common.constant.SystemConstants;
import com.duojuhe.common.exception.base.DuoJuHeException;
import com.duojuhe.common.result.ErrorCodes;
import com.duojuhe.common.result.ServiceResult;
import com.duojuhe.common.utils.idgenerator.UUIDUtils;
import com.duojuhe.common.utils.page.PageHelperUtil;
import com.duojuhe.common.utils.tree.TreeBaseBean;
import com.duojuhe.common.utils.tree.TreeUtil;
import com.duojuhe.coremodule.BaseService;
import com.duojuhe.coremodule.info.entity.InfoCategory;
import com.duojuhe.coremodule.info.entity.InfoNews;
import com.duojuhe.coremodule.info.mapper.InfoCategoryMapper;
import com.duojuhe.coremodule.info.mapper.InfoNewsMapper;
import com.duojuhe.coremodule.info.pojo.dto.category.*;
import com.duojuhe.coremodule.info.service.InfoCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
public class InfoCategoryServiceImpl  extends BaseService implements InfoCategoryService {
    @Resource
    private InfoCategoryMapper infoCategoryMapper;
    @Resource
    private InfoNewsMapper infoNewsMapper;
    /**
     * 【查询所有信息分类】查询可供前端选择使用的信息分类
     * @param req
     * @return
     */
    @DataScopeFilter
    @Override
    public ServiceResult<List<QueryInfoCategoryTreeRes>> queryInfoCategoryTreeResList(QueryInfoCategoryTreeReq req) {
        PageHelperUtil.defaultOrderBy("sort desc,createTime desc,categoryId desc");
        List<QueryInfoCategoryTreeRes> deptList = infoCategoryMapper.queryInfoCategoryTreeResList(req);
        List<TreeBaseBean> tList = TreeUtil.treeList(deptList);
        return ServiceResult.ok(tList);
    }


    /**
     * 【查询所有信息分类】查询可供前端选择使用的信息分类
     * @param req
     * @return
     */
    @DataScopeFilter(dataScope = DataScopeConstants.TENANT_ALL_DATA)
    @Override
    public ServiceResult<List<QueryInfoCategoryTreeRes>> querySelectInfoCategoryTreeResList(QueryInfoCategoryTreeReq req) {
        PageHelperUtil.defaultOrderBy("sort desc,createTime desc,categoryId desc");
        List<QueryInfoCategoryTreeRes> deptList = infoCategoryMapper.queryInfoCategoryTreeResList(req);
        List<TreeBaseBean> tList = TreeUtil.treeList(deptList);
        return ServiceResult.ok(tList);
    }

    /**
     * 【保存】信息分类信息
     * @param req
     * @return
     */
    @Override
    public ServiceResult saveInfoCategory(SaveInfoCategoryReq req) {
        //信息分类ID
        String categoryId = UUIDUtils.getUUID32();
        //当前登录用户
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //获取父级信息分类对象
        BuildParentInfoCategoryReq buildParentInfoCategory = buildParentInfoCategoryReqByParentId(req.getParentId(),categoryId,userTokenInfoVo);
        //租户id
        String tenantId = buildParentInfoCategory.getTenantId();
        //检查分类名称
        checkInfoCategoryName(req.getCategoryName(),tenantId);
        //信息分类层级路径
        String categoryPath = buildParentInfoCategory.getCategoryPath();
        //信息分类父级ID
        String parentId = buildParentInfoCategory.getParentId();
        //创建分类所属部门
        String createDeptId = buildParentInfoCategory.getCreateDeptId();
        //当前时间
        Date date = new Date();
        InfoCategory infoCategory = new InfoCategory();
        infoCategory.setCategoryId(categoryId);
        infoCategory.setParentId(parentId);
        infoCategory.setCategoryName(req.getCategoryName());
        infoCategory.setCategoryPath(categoryPath);
        infoCategory.setCreateTime(date);
        infoCategory.setUpdateTime(date);
        infoCategory.setSort(req.getSort());
        infoCategory.setCreateUserId(userTokenInfoVo.getUserId());
        infoCategory.setUpdateUserId(userTokenInfoVo.getUserId());
        infoCategory.setCreateDeptId(createDeptId);
        infoCategory.setTenantId(tenantId);
        infoCategoryMapper.insertSelective(infoCategory);
        return ServiceResult.ok(categoryId);
    }

    /**
     * 【修改】信息分类信息
     * @param req
     * @return
     */
    @Override
    public ServiceResult updateInfoCategory(UpdateInfoCategoryReq req) {
        //分类id
        String categoryId = req.getCategoryId();
        InfoCategory infoCategoryOld = infoCategoryMapper.selectByPrimaryKey(categoryId);
        if (infoCategoryOld == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //当前登录人
        UserTokenInfoVo userTokenInfoVo = getCurrentLoginUserInfoDTO();
        //获取父级信息分类对象
        BuildParentInfoCategoryReq buildParentInfoCategory = buildParentInfoCategoryReqByParentId(req.getParentId(),categoryId,userTokenInfoVo);
        //信息分类层级路径
        String categoryPath = buildParentInfoCategory.getCategoryPath();
        //信息分类父级ID
        String parentId = buildParentInfoCategory.getParentId();
        //租户id
        String tenantId = buildParentInfoCategory.getTenantId();
        //创建分类所属部门
        String createDeptId = buildParentInfoCategory.getCreateDeptId();
        //检查信息分类名称是不是自己
        if (!infoCategoryOld.getCategoryName().equals(req.getCategoryName())){
            //检查分类名称
            checkInfoCategoryName(req.getCategoryName(),tenantId);
        }
        //检查父级ID是不是自己
        if (infoCategoryOld.getCategoryId().equals(parentId)) {
            return ServiceResult.fail(ErrorCodes.INFO_CATEGORY_PARENT_NOT_SELF);
        }
        //检查父级ID是不是自己的下级
        if (!StringUtils.equals(SystemConstants.UNKNOWN_ID, parentId)) {
            if (checkChildren(parentId, infoCategoryOld.getCategoryId())) {
                return ServiceResult.fail(ErrorCodes.INFO_CATEGORY_PARENT_NOT_SELF_CHILDREN);
            }
        }

        //当前时间
        Date date = new Date();
        InfoCategory infoCategory = new InfoCategory();
        infoCategory.setCategoryId(categoryId);
        infoCategory.setParentId(parentId);
        infoCategory.setCategoryName(req.getCategoryName());
        infoCategory.setCategoryPath(categoryPath);
        infoCategory.setUpdateTime(date);
        infoCategory.setSort(req.getSort());
        infoCategory.setUpdateUserId(userTokenInfoVo.getUserId());
        infoCategory.setCreateDeptId(createDeptId);
        infoCategory.setTenantId(tenantId);
        infoCategoryMapper.updateByPrimaryKeySelective(infoCategory);
        return ServiceResult.ok(categoryId);
    }

    /**
     * 【删除】根据信息分类ID删除信息分类，注意一次仅能删除一个信息分类，存在绑定关系的则不能删除
     * @param req
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ServiceResult deleteInfoCategoryByCategoryId(InfoCategoryIdReq req) {
        String categoryId = req.getCategoryId();
        InfoCategory infoCategoryOld = infoCategoryMapper.selectByPrimaryKey(categoryId);
        if (infoCategoryOld == null) {
            return ServiceResult.fail(ErrorCodes.PARAM_ERROR);
        }
        //检查是否存在子分类信息
        checkInfoCategoryChildren(categoryId);
        //判断分类是否被信息关联使用
        checkRelationInfoNews(categoryId);
        //分类删除
        infoCategoryMapper.deleteByPrimaryKey(categoryId);
        return ServiceResult.ok(categoryId);
    }


    /**
     * 【私有方法，辅助其他接口方法使用】 根据分类id查询是否存在发布信息关联
     */
    private void checkRelationInfoNews(String categoryId) {
        if (StringUtils.isBlank(categoryId)){
            throw new DuoJuHeException(ErrorCodes.INFO_CATEGORY_RELATION_NEWS_NOT_DELETE);
        }
        Example example = new Example(InfoNews.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("categoryId", categoryId);
        if(infoNewsMapper.selectByExample(example).size()>0){
            throw new DuoJuHeException(ErrorCodes.INFO_CATEGORY_RELATION_NEWS_NOT_DELETE);
        }
    }

    /**
     * 【私有方法，辅助其他接口方法使用】 检查是否存在子分类信息
     */
    private void checkInfoCategoryChildren(String parentId) {
        if (StringUtils.isBlank(parentId)){
            throw new DuoJuHeException(ErrorCodes.INFO_CATEGORY_EXIST_CHILDREN_NOT_DELETE);
        }
        Example example = new Example(InfoCategory.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("parentId", parentId);
        if (infoCategoryMapper.selectByExample(example).size() > 0) {
            throw new DuoJuHeException(ErrorCodes.INFO_CATEGORY_EXIST_CHILDREN_NOT_DELETE);
        }
    }

    /**
     * 【私有方法，辅助其他接口方法使用】 查询分类名称是否已经存在
     */
    private void checkInfoCategoryName(String categoryName,String tenantId) {
        if (StringUtils.isBlank(categoryName)||StringUtils.isBlank(tenantId)){
            throw new DuoJuHeException(ErrorCodes.INFO_CATEGORY_NAME_EXIST);
        }
        Example example = new Example(InfoCategory.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("categoryName", categoryName);
        criteria.andEqualTo("tenantId", tenantId);
        if(infoCategoryMapper.selectByExample(example).size()>0){
            throw new DuoJuHeException(ErrorCodes.INFO_CATEGORY_NAME_EXIST);
        }
    }

    /**
     * 【私有方法，辅助其他接口方法使用】 检测所选项是不是当前id的子项
     */
    private boolean checkChildren(String categoryId, String parentId) {
        if (StringUtils.isBlank(categoryId)){
            return true;
        }
        InfoCategory infoCategory = infoCategoryMapper.selectByPrimaryKey(categoryId);
        if (infoCategory==null){
            return true;
        }
        String newPid = infoCategory.getParentId();
        if (newPid.equals(parentId)) {
            return true;
        } else {
            if (!StringUtils.equals(newPid, SystemConstants.UNKNOWN_ID)
                    && !StringUtils.equals(newPid, parentId)) {
                checkChildren(parentId, newPid);
            }
        }
        return false;
    }


    /**
     * 获取父级
     * @param parentId
     * @return
     */
    private BuildParentInfoCategoryReq buildParentInfoCategoryReqByParentId(String parentId, String categoryId, UserTokenInfoVo userTokenInfoVo){
        BuildParentInfoCategoryReq buildParentInfoCategoryReq = new BuildParentInfoCategoryReq();
        //默认为顶级信息分类，用-1标识
        if (!StringUtils.equals(SystemConstants.UNKNOWN_ID, parentId) && StringUtils.isNotBlank(parentId)) {
            InfoCategory infoCategory = infoCategoryMapper.selectByPrimaryKey(parentId);
            if (infoCategory == null) {
                throw new DuoJuHeException(ErrorCodes.PARENT_PARAM_ERROR);
            }
            buildParentInfoCategoryReq.setCategoryPath(infoCategory.getCategoryPath() + "/" + categoryId);
            buildParentInfoCategoryReq.setParentId(infoCategory.getCategoryId());
            buildParentInfoCategoryReq.setTenantId(infoCategory.getTenantId());
            buildParentInfoCategoryReq.setCreateDeptId(infoCategory.getCreateDeptId());
        }else{
            buildParentInfoCategoryReq.setCategoryPath("/" + categoryId);
            buildParentInfoCategoryReq.setParentId(SystemConstants.UNKNOWN_ID);
            buildParentInfoCategoryReq.setTenantId(userTokenInfoVo.getTenantId());
            buildParentInfoCategoryReq.setCreateDeptId(userTokenInfoVo.getCreateDeptId());
        }
        return buildParentInfoCategoryReq;
    }
}
